/*! ******************************************************************************
 *
 * Created on 2022年3月11日
 *
 * Copyright(c) YuZhou Big Data Laboratory CO.,Ltd, 2022.  All rights reserved.
 *
 *******************************************************************************
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 ******************************************************************************/

package org.yzbdl.lanius.core.plugins.install;

import java.io.File;
import java.nio.charset.Charset;
import java.util.Map;
import java.util.concurrent.LinkedBlockingDeque;

import org.yzbdl.lanius.core.constant.LocalDir;

import com.google.common.collect.Maps;
import com.google.common.collect.Queues;

import cn.hutool.core.io.FileUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;

/**
 * @author hs@yzbdl.ac.cn
 *
 */
public class PluginInfoManager {

    private static final String jsonFileName = "plugin-info.json";

    private static PluginInfoManager pluginInfoManager = new PluginInfoManager();

    /**
     * key: pluginPath <br/>
     * value: plugin-info.json内容
     */
    private Map<String, JSONObject> pluginInfoMap = Maps.newConcurrentMap();

    /**
     * key: pluginPath <br/>
     * value: plugin-info.json文件
     */
    private Map<String, File> pluginInfoFileMap = Maps.newConcurrentMap();

    private LinkedBlockingDeque<PluginInfo> queue = Queues.newLinkedBlockingDeque();

    private PluginInfoManager() {
        new Thread(new Consumer(queue)).start();
    }

    public static PluginInfoManager getInstance() {
        return pluginInfoManager;
    }

    public void addPluginInfo(PluginInfo pluginInfo) {
        queue.offer(pluginInfo);
    }

    /**
     * @param pluginPath
     * @return
     */
    public JSONObject getPluginInfo(String pluginPath) {
        JSONObject jsonInfoObject = pluginInfoMap.get(pluginPath);
        try {
            if (jsonInfoObject == null) {
                File file = new File(pluginPath + LocalDir.separator + jsonFileName);
                jsonInfoObject = JSONUtil.readJSONObject(file, Charset.defaultCharset());
                pluginInfoMap.put(pluginPath, jsonInfoObject);
            }
        } catch (Exception e) {
            // 忽略
        }
        return jsonInfoObject;
    }

    class Consumer implements Runnable {
        private LinkedBlockingDeque<PluginInfo> queue;

        public Consumer(LinkedBlockingDeque<PluginInfo> queue) {
            this.queue = queue;
        }

        @Override
        public void run() {
            try {
                PluginInfo pluginInfo;
                while ((pluginInfo = queue.take()) != null) {
                    Thread.sleep(1);
                    writeToFile(pluginInfo);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        private void writeToFile(PluginInfo pluginInfo) {
            String pluginPath = pluginInfo.getPluginPath();
            File file = pluginInfoFileMap.get(pluginPath);
            if (file == null) {
                file = FileUtil.touch(pluginPath + LocalDir.separator + jsonFileName);
                pluginInfoFileMap.put(pluginPath, file);
            }

            JSONObject jsonInfoObject = null;
            try {
                jsonInfoObject = JSONUtil.readJSONObject(file, Charset.defaultCharset());
            } catch (Exception e) {
                jsonInfoObject = new JSONObject();
            }

            // JSONArray jsonArray = new JSONArray();
            // for (JarFileAnnotationPlugin plugin : pluginInfo.getAnnotationPlugins()) {
            // JSONObject jsonObject = new JSONObject();
            // jsonObject.put("className", plugin.getClassName());
            //
            // String jarUrl = plugin.getJarFile().getPath().substring("///".length() + LocalDir.BASE.length());
            // jsonObject.put("jarUrl", jarUrl);
            //
            // String jarFolderUrl = plugin.getPluginFolder().getPath()
            // .substring("///".length() + LocalDir.BASE.length());
            // jsonObject.put("jarFolderUrl", jarFolderUrl);
            //
            // jsonArray.add(jsonObject);
            // }

            jsonInfoObject.put(pluginInfo.getAnnotationClassName(), pluginInfo.getAnnotationPlugins());

            FileUtil.writeString(jsonInfoObject.toJSONString(3), file, Charset.defaultCharset());

            pluginInfoMap.put(pluginInfo.getPluginPath(), jsonInfoObject);
        }

    }

}
